package com.xu.base.advice;

import com.xu.base.enums.ResponseCodeEnum;
import com.xu.base.exception.ServiceException;
import com.xu.base.model.BaseResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.reactive.function.client.WebClientRequestException;

import java.net.ConnectException;
import java.util.stream.Collectors;

/**
 * 异常统一处理
 *
 * @Author: 许乾伟
 * @Date: 2024/3/21 15:48
 */
@Slf4j
@RestControllerAdvice
public class ControllerExceptionAdvice {
    /**
     * 通用异常
     * @param ex 异常
     * @return 通用返回对象
     */
    @ExceptionHandler(Exception.class)
    public BaseResponse handel(Exception ex){
        BaseResponse response = new BaseResponse();
        response.setCode(ResponseCodeEnum.FAIL.getCode());
        response.setMsg(ex.getMessage());
        log.error("异常："+ex);
        return response;
    }
    /**
     * 服务异常通用处理
     * @param ex 异常
     * @return 通用返回对象
     */
    @ExceptionHandler(ServiceException.class)
    public BaseResponse handel(ServiceException ex){
        BaseResponse response = new BaseResponse();
        response.setCode(ex.getCode());
        response.setMsg(ex.getMessage());
        log.error("异常："+ex);
        return response;
    }

    /**
     * 入参格式异常处理
     * @param ex 异常
     * @return 通用返回对象
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public BaseResponse handel(HttpMessageNotReadableException ex){
        BaseResponse response = new BaseResponse();
        response.setCode(ResponseCodeEnum.DATA_FAILED.getCode());
        response.setMsg("入参格式异常");
        log.error("异常："+ex);
        return response;
    }
    /**
     * 处理Get请求中 使用@Valid 验证路径中请求实体校验失败后抛出的异常
     * @param ex 异常
     * @return 通用返回对象
     */
    @ExceptionHandler(BindException.class)
    public BaseResponse handel(BindException ex){
        String message = ex.getBindingResult().getAllErrors().stream().map(n->n.getDefaultMessage()).collect(Collectors.joining());
        BaseResponse response = new BaseResponse();
        response.setCode(ResponseCodeEnum.DATA_FAILED.getCode());
        response.setMsg(message);
        log.error("异常："+ex);
        return response;
    }

    /**
     * 处理请求参数格式错误 @RequestBody上validate失败后抛出的异常是MethodArgumentNotValidException异常
     * @param ex 异常
     * @return 通用返回对象
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public BaseResponse handel(MethodArgumentNotValidException ex){
        String message = ex.getBindingResult().getAllErrors().stream().map(n->n.getDefaultMessage()).collect(Collectors.joining(","));
        BaseResponse response = new BaseResponse();
        response.setCode(ResponseCodeEnum.DATA_FAILED.getCode());
        response.setMsg(message);
        log.error("异常："+ex);
        return response;
    }

    /**
     * 处理文件上传大小异常
     * @param ex 异常
     * @return 通用返回对象
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public BaseResponse handel(MaxUploadSizeExceededException ex){
        BaseResponse response = new BaseResponse();
        response.setCode(ResponseCodeEnum.HANDEL_FAILED.getCode());
        response.setMsg("上传文件超出限制");
        log.error("异常："+ex);
        return response;
    }

    /**
     * 处理WebClient请求异常
     * @param ex 异常
     * @return 通用返回对象
     */
    @ExceptionHandler(WebClientRequestException.class)
    public BaseResponse handel(WebClientRequestException ex){
        BaseResponse response = new BaseResponse();
        response.setCode(ResponseCodeEnum.HANDEL_FAILED.getCode());
        response.setMsg(ex.getMethod()+"请求["+ex.getUri()+"]无法访问");
        log.error("异常："+ex);
        return response;
    }

    /**
     * 服务器连接异常
     * @param ex 异常
     * @return 通用返回对象
     */
    @ExceptionHandler(ConnectException.class)
    public BaseResponse handel(ConnectException ex){
        BaseResponse response = new BaseResponse();
        response.setCode(ResponseCodeEnum.HANDEL_FAILED.getCode());
        response.setMsg("连接异常");
        log.error("异常："+ex);
        return response;
    }
}
